odhcpd: improve RFC9096 § 3.5 SLAAC compliance
authorÁlvaro Fernández Rojas <[email protected]>
Thu, 7 Aug 2025 15:38:22 +0000 (17:38 +0200)
committerÁlvaro Fernández Rojas <[email protected]>
Wed, 1 Oct 2025 16:25:56 +0000 (18:25 +0200)
commitcdb9e5b655fc6e7f4e9f340408e21231c943279c
treec019fb29b8d7009c183243099ec5c1d271530608
parentbc9f9d93d4d6b8feb7b19235d7f0371480fc679d
odhcpd: improve RFC9096 § 3.5 SLAAC compliance

When a CE router provides LAN-side address-configuration information
via SLAAC:

*  A CE router sending RAs that advertise prefixes belonging to a
   dynamically learned prefix (e.g., via DHCPv6-PD) SHOULD record, on
   stable storage, the list of prefixes being advertised via PIOs on
   each network segment and the state of the "A" and "L" flags of the
   corresponding PIOs.

*  Upon changes to the advertised prefixes, and after bootstrapping,
   the CE router advertising prefix information via SLAAC proceeds as
   follows:

   -  Any prefixes that were previously advertised by the CE router
      via PIOs in RA messages, but that have now become stale, MUST
      be advertised with PIOs that have the "Valid Lifetime" and the
      "Preferred Lifetime" set to 0 and the "A" and "L" bits
      unchanged.

   -  The aforementioned advertisements MUST be performed for at
      least the "Valid Lifetime" previously employed for such
      prefixes.

This should be enabled by default with a folder in "/tmp" to avoid forcing
flash writes for all the users and at least handle the stale PIOs on PPPoe
reconnections. For example:
  uci set dhcp.odhcpd.piofolder="/tmp/odhcpd-piofolder"
  uci commit dhcp

There's a new ubus call which allows getting all the IPv6 RA PIOs, with
information about their lifetime and stale status:
  ubus call dhcp ipv6ra
  {
    "interfaces": {
      "br-lan": [
        {
          "lifetime": 5390,
          "prefix": "2001:db8:0:100::/64",
          "stale": true
        },
        {
          "prefix": "2001:db8:0:200::/64",
          "stale": false
        },
        {
          "prefix": "fd00::/64",
          "stale": false
        }
      ],
      "eth1.10": [
        {
          "lifetime": 5390,
          "prefix": "2001:db8:0:110::/64",
          "stale": true
        },
        {
          "prefix": "2001:db8:0:210::/64",
          "stale": false
        },
        {
          "prefix": "fd00:0:0:10::/64",
          "stale": false
        }
      ]
    }
  }

The current implementation performs a flash write per interface whenever
a new prefix is added or an existing prefix becomes stale.
Since some ISPs assign static or semi-static prefixes to their customers,
it should be up to the user to enable flash writes when needed.

Link: https://github.com/openwrt/odhcpd/pull/256
Signed-off-by: Álvaro Fernández Rojas <[email protected]>
CMakeLists.txt
README
src/config.c
src/netlink.c
src/odhcpd.h
src/router.c
src/ubus.c